package factory

import (
	"fmt"

	"github.com/example-user/go-pocket-etl/pkg/core"
)

// sourceRegistry, processorRegistry, 和 sinkRegistry 是三大组件的注册中心。
// 它们是实现 Go-Pocket-ETL 可扩展性的核心：任何新的组件只要在这里注册，
// 就能被配置文件中的 "type" 字段动态调用。
//
// 这种模式利用了 Go 的 init() 函数特性：每个组件包（例如 `sources/csv`）
// 在自己的 init() 函数中调用 RegisterSource, RegisterProcessor, 或 RegisterSink，
// 从而将自己“注入”到主程序中。这使得主程序与具体组件实现完全解耦。
var (
	sourceRegistry    = make(map[string]core.SourceCreator)
	processorRegistry = make(map[string]core.ProcessorCreator)
	sinkRegistry      = make(map[string]core.SinkCreator)
)

// RegisterSource 将一个 Source 构造函数注册到工厂。
// 这个函数应该在包的 init() 函数中被调用。
// 为了保证启动时的稳定性和可预测性，如果重复注册同名组件，程序会直接 panic。
func RegisterSource(name string, creator core.SourceCreator) {
	if _, exists := sourceRegistry[name]; exists {
		panic(fmt.Sprintf("FATAL: Source with name '%s' is already registered", name))
	}
	sourceRegistry[name] = creator
}

// RegisterProcessor 将一个 Processor 构造函数注册到工厂。
// (实现逻辑和 RegisterSource 类似)
func RegisterProcessor(name string, creator core.ProcessorCreator) {
	if _, exists := processorRegistry[name]; exists {
		panic(fmt.Sprintf("FATAL: Processor with name '%s' is already registered", name))
	}
	processorRegistry[name] = creator
}

// RegisterSink 将一个 Sink 构造函数注册到工厂。
// (实现逻辑和 RegisterSource 类似)
func RegisterSink(name string, creator core.SinkCreator) {
	if _, exists := sinkRegistry[name]; exists {
		panic(fmt.Sprintf("FATAL: Sink with name '%s' is already registered", name))
	}
	sinkRegistry[name] = creator
}

// CreateSource 根据名称（即配置文件中的 `type`）从注册表中查找并实例化一个 Source。
func CreateSource(name string) (core.Source, error) {
	creator, ok := sourceRegistry[name]
	if !ok {
		return nil, fmt.Errorf("factory error: no source registered with name: %s", name)
	}
	return creator(), nil
}

// CreateProcessor 根据名称实例化一个 Processor。
func CreateProcessor(name string) (core.Processor, error) {
	creator, ok := processorRegistry[name]
	if !ok {
		return nil, fmt.Errorf("factory error: no processor registered with name: %s", name)
	}
	return creator(), nil
}

// CreateSink 根据名称实例化一个 Sink。
func CreateSink(name string) (core.Sink, error) {
	creator, ok := sinkRegistry[name]
	if !ok {
		return nil, fmt.Errorf("factory error: no sink registered with name: %s", name)
	}
	return creator(), nil
}
